﻿#include <iostream>
#include <EmbedRes.hpp>
#include <filesystem>
#include <unordered_map>
#include <vector>
#include <thread>
#include <fstream>
#include <webui.hpp>
#include "UserManager.h"
#include "Utils/json.hpp"
#include "Utils/EnvEncode.h"
// By Zero123
namespace fs = std::filesystem;
using json = nlohmann::json;

#ifdef _WEB_DEBUG_PATH
	// 调试模式下解析文件数据
	static std::vector<unsigned const char*>* debugGetStaticFileData(const fs::path& p)
	{
		static std::unordered_map<std::string, std::vector<unsigned const char*>> fMap;
		auto fullName = p.generic_string();
		if (fMap.find(fullName) != fMap.end())
		{
			return &fMap[fullName];
		}
		// 尝试匹配文件
		if (fs::is_regular_file(p))
		{
			std::ifstream file(p, std::ios::binary | std::ios::ate);  // 打开并移动到末尾
			std::streamsize size = file.tellg();
			file.seekg(0, std::ios::beg);  // 回到开头
			std::vector<unsigned const char*> buffer(size);
			if (file.read(reinterpret_cast<char*>(buffer.data()), size))
			{
				fMap[fullName] = std::move(buffer);
				return &fMap[fullName];
			}
		}
		return nullptr;
	}

#endif

// 重定向文件系统
static const void* filesHandler(const char* filename, int* length)
{
	auto fullPath = fs::path(filename).generic_string();
#ifdef _WEB_DEBUG_PATH
	static fs::path testPath{ _WEB_DEBUG_PATH };
	// 自定义调试映射路径
	auto filePath = testPath / fs::path(fullPath).relative_path();
	std::cout << "[DEBUG_FILE_REQUEST]: " << filePath << "\n";
	auto fData = debugGetStaticFileData(filePath);
	if (fData != nullptr)
	{
		*length = fData->size();
		return static_cast<const void*>(fData->data());
	}
#else
	#ifdef _DEBUG
		std::cout << "[FILE_REQUEST]: " << fullPath << "\n";
	#endif
		if (EmbedRes::resourceMap.find(fullPath) != EmbedRes::resourceMap.end())
		{
			auto& resource = EmbedRes::resourceMap.at(fullPath);
			*length = resource.second;
			return resource.first;
		}
#endif // _WEB_DEBUG_PATH
#ifdef _DEBUG
		std::cout << "[FILE_ERROR]: " << filename << "\n";
#endif
	return nullptr;
}

// API接口 获取历史记录
static void API_GET_HIS_RENDER_LIST(webui::window::event* event)
{
	event->return_string(UserManager::CACHE_GET_USER_HISTORY_LIST().dump());
}

static webui::window* currentWindows = nullptr;

static std::mutex currentMutex;

// mod信息查询
static void API_SEARCH_MOD_INFO(webui::window::event* event)
{
	static bool workingState = false;
	if (event->get_size() <= 0)
	{
		return;
	}
	std::string modId = event->get_string(0);
	if (modId.empty())
	{
		return;
	}
	std::lock_guard<std::mutex> lock(currentMutex);
	if (workingState)
	{
		return;
	}
	workingState = true;
	std::thread t([&, modId]() {
		// 异步线程处理post
		auto jo = UserManager::FORMAT_POST_MOD_INFO(modId);
		std::lock_guard<std::mutex> lock(currentMutex);
		workingState = false;
		if (currentWindows != nullptr)
		{
			if (jo.value("cpp_state", -1) == 0)
			{
				UserManager::ADD_USER_HISTORY(jo.at("entity").value("res_name", "Unknow"), modId);
			}
			// 写入待渲染信息
			currentWindows->run("webui.ipcRenderInfo = " + jo.dump());
		}
	});
	t.detach();
}

// GLOBAL EVENT
static void globalEventHandler(webui::window::event* event)
{
	if (event->event_type == WEBUI_EVENT_CONNECTED)
	{
		if (currentWindows != nullptr)
		{
			// WebUI库v2.4版本并没有提供js前端的事件监听功能 需要自己包装实现
			std::lock_guard<std::mutex> lock(currentMutex);
			currentWindows->run("webui.ipcConnectedState = true;");
		}
	}
}

int main()
{
	Encoding::initEnvcode();
	webui::window myWindow;
	currentWindows = &myWindow;
	myWindow.set_file_handler(filesHandler);
	myWindow.bind("", globalEventHandler);
	myWindow.bind("_API_SEARCH_MOD_INFO", API_SEARCH_MOD_INFO);
	myWindow.bind("_API_GET_HIS_RENDER_LIST", API_GET_HIS_RENDER_LIST);
	myWindow.set_size(800, 520);
	myWindow.show("index.html");
	webui::wait();
	currentWindows = nullptr;
	return 0;
}

#ifndef _DEBUG
// Windows Release窗口模式下运行
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { main(); }
#endif
